package com.maxafaa.dodgeballoon;


import java.util.ArrayList;
import java.util.Random;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainSurfaceView extends SurfaceView  implements SurfaceHolder.Callback, Runnable, SensorEventListener{

	private boolean m_is_running;
	private SurfaceHolder m_surfaceholder;
	private static int s_screen_width, s_screen_height;
	private Paint m_paint;
	private Thread m_mainthread;
	private Canvas m_lockcanvas;
	private float m_touch_x, m_touch_y;
	//Motion Sensor
	private Context m_context;
	private SensorManager m_sensor_manager;
	private Sensor m_sensor;
	private float m_sensor_x_value, m_sensor_y_value, m_sensor_z_value;
	
	//physic object
	private ArrayList<PhysicObject> m_balloon_list;
	private Random m_random;
	private final int M_MIN_BALLOON_RADIUS = 5;
	private final int M_MAX_BALLOON_RADIUS_RANGE = 45;
	private final int M_BALLOON_SURVIVAL_TIME = 2700;
	
	
	//mc
	private int m_mc_head_x, m_mc_head_y;
	private final int M_MC_HEIGHT = 20;
	private final int M_MC_WALL_DISTANCE = 30;
	private int m_user_score;
	private int m_user_best_score;
	public static final String PREFS_NAME = "PlayerPrefsFile";//save record
	
	//rule
	private final int M_BALL_RELEASE_DELAY_DECREASE_TIME = 500;
	private int m_ball_release_level_time;
	private double m_start_level_time;
	private final int M_STATE_START = 0; 
	private final int M_STATE_GAMEPLAY = 1;
	private final int M_STATE_RESTART = 2;
	private int m_current_state;
	private boolean is_new_higth_scrore;
	
	//align
	private final int M_BUTTON_WIDTH = 50;
	private final int M_TEXT_TITLE_OFFSET_X = 165;
	private final int M_TEXT_SCORE_OFFSET_X = 75;
	private final int M_TEXT_SCORE_OFFSET_Y = 50;
	private final int M_BUTTON_START_TEXT_OFFSET_X = 30;
	private final int M_BUTTON_START_TEXT_OFFSET_Y = 5;
	private final int M_BUTTON_RESTART_TEXT_OFFSET_X = 40;
	private final int M_BUTTON_RESTART_TEXT_OFFSET_Y = 5;
	
	
	public MainSurfaceView(Context context) {
		super(context);
		m_context = context;
		m_surfaceholder = getHolder();
		m_surfaceholder.addCallback(this);		
		setFocusable(true);
		s_screen_width = context.getResources().getDisplayMetrics().widthPixels;
		s_screen_height = context.getResources().getDisplayMetrics().heightPixels;
	}

	private void Initialize(){
		
		m_sensor_manager = (SensorManager) m_context.getSystemService(Context.SENSOR_SERVICE);
		m_sensor = m_sensor_manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		m_sensor_manager.registerListener(this, m_sensor, SensorManager.SENSOR_DELAY_GAME);
		m_sensor_x_value = 0;
		m_sensor_y_value = 0;
		m_sensor_z_value = 0;
		m_user_score = 0;
		m_current_state = 0;
		m_user_best_score = LoadBestScore();
		is_new_higth_scrore = false;
		m_random = new Random();
		m_balloon_list = new ArrayList<PhysicObject>();
		m_mc_head_x = s_screen_width/2;
		m_mc_head_y = s_screen_height - M_MC_HEIGHT;
		m_start_level_time = 0;
		m_ball_release_level_time = 5000;
		m_touch_x = -1;
		m_touch_y = -1;
		m_paint = new Paint();
		m_mainthread = new Thread(this);
		m_mainthread.start();
		m_is_running = true;		
		
	}
	
	private void SaveBestScore(){
		SharedPreferences settings = m_context.getSharedPreferences(PREFS_NAME, android.content.Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();
		editor.putInt("BestScore", m_user_best_score);
		editor.commit();
	}
	
	private int LoadBestScore(){
		SharedPreferences settings = m_context.getSharedPreferences(PREFS_NAME, android.content.Context.MODE_PRIVATE );
		return settings.getInt("BestScore", 0);
		
	}
	
	
	public void GameCreate(){

	}
	
	public void GameStart(){

	}
	
	public void GamePause(){
		if(m_sensor_manager != null)
			m_sensor_manager.unregisterListener(this);
	}
	
	public void GameResume(){
		if(m_sensor_manager != null)
			m_sensor_manager.registerListener(this, m_sensor, SensorManager.SENSOR_DELAY_GAME);

	}
	
	public void GameStop(){
		SaveBestScore();
	}
	
	public void GameDestroy(){
		RemoveAllBird();
		m_balloon_list = null;
	}
	
	public void GameRestart(){

	}
	
	private void GameUpdate(){
		if(m_current_state == M_STATE_START){
			
		}else if(m_current_state == M_STATE_GAMEPLAY){
			if(System.currentTimeMillis() - m_start_level_time > m_ball_release_level_time){
				m_start_level_time = System.currentTimeMillis();
				if(m_ball_release_level_time > M_BALL_RELEASE_DELAY_DECREASE_TIME)
					m_ball_release_level_time -= M_BALL_RELEASE_DELAY_DECREASE_TIME;				
				int new_balloon_radius = M_MIN_BALLOON_RADIUS + m_random.nextInt(M_MAX_BALLOON_RADIUS_RANGE);
				m_balloon_list.add(new PhysicObject((int)new_balloon_radius + m_random.nextInt(s_screen_width - new_balloon_radius*2), (int)new_balloon_radius, 0, 0, 0, 0, getWidth(), getHeight()));
				m_balloon_list.get(m_balloon_list.size() - 1).setRadius(new_balloon_radius);
			}
			for(int i = 0; i < m_balloon_list.size(); i ++){
				m_balloon_list.get(i).Update();				
				if(CheckPointInCircle(m_mc_head_x, m_mc_head_y, m_balloon_list.get(i).getPositionX(), m_balloon_list.get(i).getPositionY(), m_balloon_list.get(i).getRadius()))
					m_current_state = M_STATE_RESTART;				
			}
			for(int i = m_balloon_list.size() - 1; i >= 0 ; i --){
				if(System.currentTimeMillis() - m_balloon_list.get(i).getSurvivalTime() > M_BALLOON_SURVIVAL_TIME){
					m_balloon_list.remove(i);
					m_user_score += 1;
				}
			}
		}else if(m_current_state == M_STATE_RESTART){
			
		}
	}	
	
	private void GameDraw(Canvas canvas){
		canvas.drawColor(Color.WHITE);
		m_paint.setColor(Color.BLACK);
		m_paint.reset();
//		canvas.drawText("X Value: " + m_sensor_x_value, 5, 15, m_paint);
//		canvas.drawText("Y Value: " + m_sensor_y_value, 5, 30, m_paint);
//		canvas.drawText("Z Value: " + m_sensor_z_value, 5, 45, m_paint);
		
		//draw mc
		m_paint.setStrokeWidth(2);
		canvas.drawLine(m_mc_head_x, m_mc_head_y, m_mc_head_x, s_screen_height, m_paint);
		
		m_paint.setColor(Color.BLUE);
		m_paint.setAntiAlias(true);
		for(int i = 0; i < m_balloon_list.size(); i ++){
			canvas.drawCircle(m_balloon_list.get(i).getPositionX(), m_balloon_list.get(i).getPositionY(), m_balloon_list.get(i).getRadius(), m_paint);			
		}
		
		if(m_current_state == M_STATE_START){
			m_paint.setColor(Color.YELLOW);
			m_paint.setTextSize(100);
			m_paint.setStrokeWidth(12);
			canvas.drawText("DODGE", s_screen_width/2 - M_TEXT_TITLE_OFFSET_X, s_screen_height/4, m_paint);
			m_paint.setColor(Color.BLACK);
			canvas.drawRect(s_screen_width/2 - M_BUTTON_WIDTH, s_screen_height/2 - M_BUTTON_WIDTH/2, s_screen_width/2 + M_BUTTON_WIDTH, s_screen_height/2 + M_BUTTON_WIDTH/2, m_paint);
			m_paint.setColor(Color.GREEN);
			m_paint.setTextSize(20);
			m_paint.setStrokeWidth(3);
			canvas.drawText("START", s_screen_width/2 - M_BUTTON_START_TEXT_OFFSET_X, s_screen_height/2 + M_BUTTON_START_TEXT_OFFSET_Y, m_paint);
		}
		if(m_current_state == M_STATE_GAMEPLAY){
			m_paint.setStrokeWidth(2);	
			m_paint.setColor(Color.BLACK);
			canvas.drawText("Best: " + m_user_best_score, 5, 15, m_paint);
			canvas.drawText("Score: " + m_user_score, 5, 30, m_paint);
		}
		if(m_current_state == M_STATE_RESTART){
			m_paint.setColor(Color.BLACK);
			m_paint.setTextSize(40);
			m_paint.setStrokeWidth(3);			
			canvas.drawText("SCORE:", s_screen_width/2 - M_TEXT_SCORE_OFFSET_X, s_screen_height/2 - M_TEXT_SCORE_OFFSET_Y*2, m_paint);
			canvas.drawText("BEST:", s_screen_width/2 - M_TEXT_SCORE_OFFSET_X, s_screen_height/2 - M_TEXT_SCORE_OFFSET_Y, m_paint);
			m_paint.setColor(Color.MAGENTA);
			canvas.drawText("" + m_user_score, s_screen_width/2 + M_TEXT_SCORE_OFFSET_X, s_screen_height/2 - M_TEXT_SCORE_OFFSET_Y*2, m_paint);
			canvas.drawText("" + m_user_best_score, s_screen_width/2 + M_TEXT_SCORE_OFFSET_X, s_screen_height/2 - M_TEXT_SCORE_OFFSET_Y, m_paint);			
			if(m_user_score > m_user_best_score){
				m_user_best_score = m_user_score;
				is_new_higth_scrore = true;
			}
			if(is_new_higth_scrore){
				m_paint.setColor(Color.RED);
				canvas.drawText("NEW", s_screen_width/2 + M_TEXT_SCORE_OFFSET_X*2, s_screen_height/2 - M_TEXT_SCORE_OFFSET_Y, m_paint);
			}
			m_paint.setColor(Color.BLACK);
			canvas.drawRect(s_screen_width/2 - M_BUTTON_WIDTH, s_screen_height/2 - M_BUTTON_WIDTH/2, s_screen_width/2 + M_BUTTON_WIDTH, s_screen_height/2 + M_BUTTON_WIDTH/2, m_paint);
			m_paint.setColor(Color.GREEN);
			m_paint.setTextSize(20);
			m_paint.setStrokeWidth(3);
			canvas.drawText("RESTART", s_screen_width/2 - M_BUTTON_RESTART_TEXT_OFFSET_X, s_screen_height/2 + M_BUTTON_RESTART_TEXT_OFFSET_Y, m_paint);
		}		
	}
	
	private boolean CheckPointInRect(int px, int py, int rx, int ry, int rw, int rh){
		if(px >= rx && px <= (rx + rw) && py >= ry && py <= (ry + rh))
			return true;
		return false;
	}
	
	public boolean RemoveAllBird(){		
		if(m_balloon_list.size() > 0){
			for(int i = m_balloon_list.size() - 1; i >= 0; i --){
				m_balloon_list.get(i).Destroy();
				m_balloon_list.remove(i);
			}
			return true;
		}else{
			return false;
		}
	}
	
	private boolean CheckPointInCircle(int point_x, int point_y, int circle_heart_x, int circle_heart_y, int radius){
		double distance = Math.sqrt(Math.pow((circle_heart_x - point_x), 2) + Math.pow((circle_heart_y - point_y), 2));
		if(distance <= radius)
			return true;
		return false;
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent e){
		super.onTouchEvent(e);
		m_touch_x = e.getX();
		m_touch_y = e.getY();
		if(m_current_state == M_STATE_START){
			if(CheckPointInRect((int)m_touch_x, (int)m_touch_y, s_screen_width/2 - M_BUTTON_WIDTH, s_screen_height/2 - M_BUTTON_WIDTH/2, s_screen_width/2 + M_BUTTON_WIDTH, s_screen_height/2 + M_BUTTON_WIDTH/2)){
				m_current_state = M_STATE_GAMEPLAY;
			}
		}else if(m_current_state == M_STATE_GAMEPLAY){
			
		}else if(m_current_state == M_STATE_RESTART){
			if(CheckPointInRect((int)m_touch_x, (int)m_touch_y, s_screen_width/2 - M_BUTTON_WIDTH, s_screen_height/2 - M_BUTTON_WIDTH/2, s_screen_width/2 + M_BUTTON_WIDTH, s_screen_height/2 + M_BUTTON_WIDTH/2)){
				m_current_state = M_STATE_GAMEPLAY;
				RemoveAllBird();				
				m_start_level_time = 0;
				m_ball_release_level_time = 5000;
				m_user_score = 0;
				is_new_higth_scrore = false;
			}
		}
		return true;
	}
	

	@Override
	public void run() {
		while(m_is_running){
			try{
				// Thread.sleep(20);
			}catch(Exception e){}
			GameUpdate();
			m_lockcanvas = m_surfaceholder.lockCanvas(null);
			synchronized (m_surfaceholder) {
				if(m_lockcanvas != null){
					GameDraw(m_lockcanvas);
					m_surfaceholder.unlockCanvasAndPost(m_lockcanvas);
				}
			}
		}		
	}

	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		Initialize();		
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		boolean retry = true;
		m_is_running = false;
        do {
            try {
                m_mainthread.join();
                retry = false;
            } catch (InterruptedException e) {
				e.printStackTrace();
                // we will try it again and again...
            }
        }while(retry);		
	}

	@Override
	public void onAccuracyChanged(Sensor arg0, int arg1) {
		
		
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		m_sensor_x_value = event.values[0];//x > 0 => tilt to left
		m_sensor_y_value = event.values[1];//y > 0 => tilt to bottom
		m_sensor_z_value = event.values[2];//z > 0 => screen is up
		if(m_current_state == M_STATE_START){
			
		}else if(m_current_state == M_STATE_GAMEPLAY){
//			for(int i = 0; i < m_balloon_list.size(); i ++){
//				m_balloon_list.get(i).setVelocityIniX(m_balloon_list.get(i).getVelocityIniX() - m_sensor_x_value/8);								
//			}
			m_mc_head_x -= m_sensor_x_value*3;
			if(m_mc_head_x - M_MC_WALL_DISTANCE < 0)
				m_mc_head_x = M_MC_WALL_DISTANCE;
			if(m_mc_head_x + M_MC_WALL_DISTANCE > s_screen_width)
				m_mc_head_x = s_screen_width - M_MC_WALL_DISTANCE;
		}else if(m_current_state == M_STATE_RESTART){
			
		}
		
	}
}
